using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using System.Collections;

namespace Microsoft.ConnectionEngine.Registers.Core.ServiceProvider.NotificationServices
{
    [RunInstaller(true)]
    public class Installer: Microsoft.ConnectionEngine.Common.Install.Installer
    {
        const string ICF_FILENAME = "HCENotificationServiceICF.xml";
        const string ICF_INSTANCENAME = "HCENotificationService";
        const string NOTIFICATION_SERVICE_BIN_FOLDER = @"C:\Program Files\Microsoft SQL Server\90\NotificationServices\9.0.242\bin\";
        const string NSCONTROL_FILE_NAME = "nscontrol.exe";
        const string DB_OBJECT_CREATE_FILE_NAME = @"\Database Scripts\DB-CreateObjects.sql";
        const string DB_OBJECT_DESTROY_FILE_NAME = @"\Database Scripts\DB-DestroyObjects.sql";

        public string NSControlLocation
        {
            get { return NOTIFICATION_SERVICE_BIN_FOLDER; }
        }
	

        public override void Install(System.Collections.IDictionary stateSaver)
        {
            string maindirectory = this.Context.Parameters["assemblypath"];
            maindirectory = maindirectory.Substring(0, maindirectory.LastIndexOf("\\"));
            string createDBObjectFile = maindirectory + DB_OBJECT_CREATE_FILE_NAME;
            string icfFileLocation = System.IO.Path.Combine(maindirectory, ICF_FILENAME);

            #region Creates a new Notification Service Instance based on the ICF File.

            System.Diagnostics.Process createProcess = new System.Diagnostics.Process();

            createProcess.StartInfo.UseShellExecute = true;
            createProcess.StartInfo.FileName = NSCONTROL_FILE_NAME;
            createProcess.StartInfo.WorkingDirectory = NSControlLocation;
            createProcess.StartInfo.Arguments = String.Format("create -in \"{0}\" SystemName=\"{1}\" BaseDirectory=\"{2}\" SystemAdapterWebServiceURL=\"{3}\" SystemAdapterUserName=\"{4}\" SystemAdapterPassword=\"{5}\"",
                icfFileLocation,
                this.Context.Parameters["systemname"],
                maindirectory,
                this.Context.Parameters["systemadapterwebserviceurl"],
                this.Context.Parameters["systemadapterusername"],
                this.Context.Parameters["systemadapterpassword"]);

            //MessageBox.Show(String.Format(@"{0}\{1} {2}", createProcess.StartInfo.WorkingDirectory, createProcess.StartInfo.FileName, createProcess.StartInfo.Arguments));
            createProcess.Start();
            createProcess.WaitForExit();
            if (createProcess.ExitCode != 0)
                throw new System.InvalidOperationException("An error ocurred while trying to create the Change Notification Service Instance. The install cannot continue.");
            else
                stateSaver.Add("step1", "complete");
            #endregion

            #region Register the Notification Service Instance as a service.

            System.Diagnostics.Process registerProcess = new System.Diagnostics.Process();

            registerProcess.StartInfo.UseShellExecute = true;
            registerProcess.StartInfo.FileName = NSCONTROL_FILE_NAME;
            registerProcess.StartInfo.WorkingDirectory = NSControlLocation;
            registerProcess.StartInfo.Arguments = String.Format("register -name {0} -server {1} -service -serviceusername {2} -servicepassword {3}",
                ICF_INSTANCENAME,
                this.Context.Parameters["systemname"],
                this.Context.Parameters["serviceusername"],
                this.Context.Parameters["servicepassword"]);

            registerProcess.Start();
            registerProcess.WaitForExit();
            if (registerProcess.ExitCode != 0)
                throw new System.InvalidOperationException("An error ocurred while trying to register the Change Notification Service. The install cannot continue.");
            else
                stateSaver.Add("step2", "complete");
            #endregion

            #region Enable the Notification Sercice Instance
            System.Diagnostics.Process enableProcess = new System.Diagnostics.Process();

            enableProcess.StartInfo.UseShellExecute = true;
            enableProcess.StartInfo.FileName = NSCONTROL_FILE_NAME;
            enableProcess.StartInfo.WorkingDirectory = NSControlLocation;
            enableProcess.StartInfo.Arguments = String.Format("enable -name {0} -server {1} -subscriptions -subscribers",
                ICF_INSTANCENAME,
                this.Context.Parameters["systemname"],
                this.Context.Parameters["serviceusername"],
                this.Context.Parameters["servicepassword"]);

            enableProcess.Start();
            enableProcess.WaitForExit();
            if (enableProcess.ExitCode != 0)
                throw new System.InvalidOperationException("An error ocurred while trying to enable the Change Notification Service. The install cannot continue.");
            else
                stateSaver.Add("step3", "complete");
            #endregion

            #region Creating Database Items

            //MessageBox.Show(this.Context.Parameters["systemname"] + " - " +
            //    this.Context.Parameters["sprdbname"] + " - " +
            //    this.Context.Parameters["sprdbuser"] + " - " +
            //    this.Context.Parameters["sprdbpwd"]);

            ExecuteSQLScript(
                this.Context.Parameters["systemname"], 
                this.Context.Parameters["sprdbname"], 
                this.Context.Parameters["sprdbuser"], 
                this.Context.Parameters["sprdbpwd"], 
                createDBObjectFile); 

            #endregion

            stateSaver.Add("systemname", this.Context.Parameters["systemname"]);
            stateSaver.Add("sprdbname", this.Context.Parameters["sprdbname"]);
            stateSaver.Add("sprdbuser", this.Context.Parameters["sprdbuser"]);
            stateSaver.Add("sprdbpwd", this.Context.Parameters["sprdbpwd"]);
        }

        public override void Uninstall(System.Collections.IDictionary savedState)
        {
            string maindirectory = this.Context.Parameters["assemblypath"];
            maindirectory = maindirectory.Substring(0, maindirectory.LastIndexOf("\\"));

            string destroyDBObjectFile = maindirectory + DB_OBJECT_DESTROY_FILE_NAME;


            #region Destroy Database Items

            ExecuteSQLScript(
                savedState["systemname"].ToString(), 
                savedState["sprdbname"].ToString(), 
                savedState["sprdbuser"].ToString(), 
                savedState["sprdbpwd"].ToString(), 
                destroyDBObjectFile); 

            #endregion
           
            #region Unregister the Notification Service Instance

            System.Diagnostics.Process unregisterProcess = new System.Diagnostics.Process();

            unregisterProcess.StartInfo.UseShellExecute = true;
            unregisterProcess.StartInfo.FileName = NSCONTROL_FILE_NAME;
            unregisterProcess.StartInfo.WorkingDirectory = NSControlLocation;
            unregisterProcess.StartInfo.Arguments = String.Format("unregister -name {0}", ICF_INSTANCENAME);

            unregisterProcess.Start();
            unregisterProcess.WaitForExit();
            #endregion

            #region Delete the Notification Service Instance

            System.Diagnostics.Process deleteProcess = new System.Diagnostics.Process();

            deleteProcess.StartInfo.UseShellExecute = true;
            deleteProcess.StartInfo.FileName = NSCONTROL_FILE_NAME;
            deleteProcess.StartInfo.WorkingDirectory = NSControlLocation;
            deleteProcess.StartInfo.Arguments = String.Format("delete -name {0} -force", ICF_INSTANCENAME);

            deleteProcess.Start();
            deleteProcess.WaitForExit();
            #endregion
        }

        public override void Rollback(System.Collections.IDictionary savedState)
        {
            if (savedState.Contains("step3") && savedState["step3"].ToString() == "complete")
            {
                System.Diagnostics.Process disableProcess = new System.Diagnostics.Process();

                disableProcess.StartInfo.UseShellExecute = true;
                disableProcess.StartInfo.FileName = NSCONTROL_FILE_NAME;
                disableProcess.StartInfo.WorkingDirectory = NSControlLocation;
                disableProcess.StartInfo.Arguments = String.Format("disable -name {0} -server {1} -subscriptions -subscribers",
                    ICF_INSTANCENAME,
                    this.Context.Parameters["systemname"],
                    this.Context.Parameters["serviceusername"],
                    this.Context.Parameters["servicepassword"]);

                disableProcess.Start();
                disableProcess.WaitForExit();
            }


            if (savedState.Contains("step2") && savedState["step2"].ToString() == "complete")
            {
                System.Diagnostics.Process unregisterProcess = new System.Diagnostics.Process();

                unregisterProcess.StartInfo.UseShellExecute = true;
                unregisterProcess.StartInfo.FileName = NSCONTROL_FILE_NAME;
                unregisterProcess.StartInfo.WorkingDirectory = NSControlLocation;
                unregisterProcess.StartInfo.Arguments = String.Format("unregister -name {0}", ICF_INSTANCENAME);

                unregisterProcess.Start();
                unregisterProcess.WaitForExit();
            }
            
            if (savedState.Contains("step1") && savedState["step1"].ToString() == "complete")
            {
                System.Diagnostics.Process deleteProcess = new System.Diagnostics.Process();

                deleteProcess.StartInfo.UseShellExecute = true;
                deleteProcess.StartInfo.FileName = NSCONTROL_FILE_NAME;
                deleteProcess.StartInfo.WorkingDirectory = NSControlLocation;
                deleteProcess.StartInfo.Arguments = String.Format("delete -name {0} -force", ICF_INSTANCENAME);

                deleteProcess.Start();
                deleteProcess.WaitForExit();
            }

            base.Rollback(savedState);
        }
    }
}
